/*
 * HttpServer.cc
 *
 *  Created on: 2021年4月6日
 *      Author: san
 */

#include "HttpServer.h"
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <functional>
#include "Util.h"
#include "base/Logging.h"

namespace san {

HttpServer::HttpServer(EventLoop *loop, int threadNum, int port)
	:loop_(loop),
	 threadNum_(threadNum),
	 eventLoopTHreadPoll_(new EventLoopThreadPool(loop_, threadNum_)),
	 started_(false),
	 acceptChannel_(new Channel(loop_)),
	 port_(port),
	 listenFd_(socket_bind_listen(port_))
{
	acceptChannel_->setFd(listenFd_);
//	handle_for_sigpipe();
	if (setSocketNonBlocking(listenFd_) < 0)
	{
	    perror("set socket non block failed");
	    abort();
	}
}

void HttpServer::start()
{
	eventLoopTHreadPoll_->start();
	// acceptChannel_->setEvents(EPOLLIN | EPOLLET | EPOLLONESHOT);
	acceptChannel_->setEvents(EPOLLIN | EPOLLET);
	acceptChannel_->setReadHandler(std::bind(&HttpServer::handNewConn, this));
	acceptChannel_->setConnHandler(std::bind(&HttpServer::handThisConn, this));
	loop_->addToPoller(acceptChannel_, 0);
	started_ = true;
}

void HttpServer::handNewConn()
{
	struct sockaddr_in client_addr;
	memset(&client_addr, 0, sizeof (struct sockaddr_in));
	socklen_t client_addr_len = sizeof client_addr;
	int accept_fd = 0;
	while ((accept_fd = accept(listenFd_,
			(struct sockaddr *) &client_addr,
			&client_addr_len)) > 0)
	{
		EventLoop *loop = eventLoopTHreadPoll_->getNextLoop();
	    LOG << "New connection from " << inet_ntoa(client_addr.sin_addr) << ":"
	        << ntohs(client_addr.sin_port);

	    // 限制服务器的最大并发连接数
	    if (accept_fd >= MAXFDS)
	    {
	    	close(accept_fd);
	    	continue;
	    }

	    // 设为非阻塞模式
	    if (setSocketNonBlocking(accept_fd) < 0)
	    {
//	        LOG << "Set non block failed!";
	        // perror("Set non block failed!");
	        return;
	    }

	    setSocketNodelay(accept_fd);

	    std::shared_ptr<HttpData> req_info(new HttpData(loop, accept_fd));
	    req_info->getChannel()->setHolder(req_info);
	    loop->queueInLoop(std::bind(&HttpData::newEvent, req_info));
	}

	acceptChannel_->setEvents(EPOLLIN | EPOLLET);
}

HttpServer::~HttpServer() {
	// TODO Auto-generated destructor stub
}

} /* namespace san */
